package org.jeecg.modules.geo.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.modules.core.constant.DataStatusEnum;
import org.jeecg.modules.core.constant.YesOrNotEnum;
import org.jeecg.modules.geo.core.constant.BimGeoRequestDataMethod;
import org.jeecg.modules.geo.core.constant.BimGeoRequestMethod;
import org.jeecg.modules.geo.entity.BimGeoApi;
import org.jeecg.modules.geo.entity.BimGeoApp;
import org.jeecg.modules.geo.mapper.BimGeoApiMapper;
import org.jeecg.modules.geo.model.BimGeoAppAuthConfig;
import org.jeecg.modules.geo.service.IBimGeoApiService;
import org.jeecg.modules.geo.service.IBimGeoAppAuthService;
import org.jeecg.modules.geo.service.IBimGeoAppService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Description: bim_geo_api
 * @Author: jeecg-boot
 * @Date: 2022-12-05
 * @Version: V1.0
 */
@Service
@Slf4j
public class BimGeoApiServiceImpl extends ServiceImpl<BimGeoApiMapper, BimGeoApi> implements IBimGeoApiService {

    @Autowired
    private IBimGeoAppAuthService bimGeoAppAuthService;

    @Autowired
    private IBimGeoAppService bimGeoAppService;

    @Override
    public IPage<BimGeoApi> pageList(IPage<BimGeoApi> page, Wrapper<BimGeoApi> queryWrapper) {
        IPage<BimGeoApi> bimGeoApiIPage = this.page(page, queryWrapper);
        List<BimGeoApi> records = bimGeoApiIPage.getRecords();
        if (CollUtil.isNotEmpty(records)) {
            List<Integer> appIds = records.stream().map(BimGeoApi::getAppId).collect(Collectors.toList());
            List<BimGeoApp> bimGeoApps = bimGeoAppService.listByIds(appIds);
            records.forEach(item -> {
                for (BimGeoApp bimGeoApp : bimGeoApps) {
                    if (bimGeoApp.getId().equals(item.getAppId())) {
                        item.setAppName(bimGeoApp.getAppName());
                        break;
                    }
                }
            });
        }
        return bimGeoApiIPage;
    }

    @Override
    public void add(BimGeoApi bimGeoApi) {
        bimGeoApi.setDelFlag(DataStatusEnum.NORMAL.getCode());
        if (!StringUtils.isEmpty(bimGeoApi.getDataTypes())) {
            bimGeoApi.setDataTypes(bimGeoApi.getDataTypes().replaceAll("，", ","));
        }
        this.save(bimGeoApi);
    }

    @Override
    public BimGeoApi find(Integer appId, String path) {
        LambdaUpdateWrapper<BimGeoApi> queryWrapper = new LambdaUpdateWrapper<>();
        queryWrapper.eq(BimGeoApi::getAppId, appId)
                .eq(BimGeoApi::getPath, path)
                .eq(BimGeoApi::getEnableFlag, YesOrNotEnum.Y.getCode());
        List<BimGeoApi> bimGeoApis = this.getBaseMapper().selectList(queryWrapper);
        return CollectionUtils.isEmpty(bimGeoApis) ? null : bimGeoApis.get(0);
    }

    @Override
    public void update(BimGeoApi bimGeoApi) {
        if (StringUtils.isEmpty(bimGeoApi.getId())) {
            log.error("修改接口信息失败，id不能为空");
            throw new JeecgBootException("修改接口失败，id不能为空");
        }
        if (!StringUtils.isEmpty(bimGeoApi.getDataTypes())) {
            bimGeoApi.setDataTypes(bimGeoApi.getDataTypes().replaceAll("，", ","));
        }
        this.updateById(bimGeoApi);
    }

    @Override
    public List<BimGeoApi> findList(Integer appId, Integer apiType, Integer dataType) {
        LambdaUpdateWrapper<BimGeoApi> queryWrapper = new LambdaUpdateWrapper<>();
        queryWrapper.eq(BimGeoApi::getAppId, appId)
                .eq(BimGeoApi::getType, apiType)
                .eq(BimGeoApi::getEnableFlag, YesOrNotEnum.Y.getCode());
        List<BimGeoApi> bimGeoApis = this.getBaseMapper().selectList(queryWrapper);
        if (CollectionUtils.isEmpty(bimGeoApis)) {
            return null;
        }
        return bimGeoApis.stream().filter(x ->
                !StringUtils.isEmpty(x.getDataTypes()) && Arrays.asList(x.getDataTypes().split(",")).contains(dataType.toString())).collect(Collectors.toList());
    }

    @Override
    public BimGeoApi find(Integer appId, Integer apiType, Integer dataType) {
        List<BimGeoApi> bimGeoApis = this.findList(appId, apiType, dataType);
        return CollectionUtils.isEmpty(bimGeoApis) ? null : bimGeoApis.get(0);
    }

    @Override
    public HttpRequest getRequest(Integer apiId, Object requestParam) {
        BimGeoApi bimGeoApi = this.queryBimGeoApi(apiId);
        if (Objects.isNull(bimGeoApi)) {
            throw new JeecgBootException("未查询到对应api");
        }
        //查询api对应的应用
        BimGeoApp bimGeoApp = bimGeoAppService.find(BimGeoApp::getId, bimGeoApi.getAppId());
        if (Objects.isNull(bimGeoApp)) {
            throw new JeecgBootException("未查询到对应应用");
        }
        //获取鉴权配置
        BimGeoAppAuthConfig authConfig = bimGeoAppService.getAuthConfig(bimGeoApp.getId());
        //获取token信息
        String token = bimGeoAppAuthService.auth(bimGeoApi.getAppId());
        String url = bimGeoApp.getApiUrl() + bimGeoApi.getPath();
        HttpRequest request = new HttpRequest(url)
                .method(BimGeoRequestMethod.methodOf(bimGeoApi.getApiMethod()));
        if(ObjectUtil.isNotNull(authConfig)) {
            request.header(authConfig.getTokenHeaderKey(), token);
        }else{
            if (authConfig == null || YesOrNotEnum.N.getCode().equals(authConfig.getAuthEnableFlag())) {
                log.info("无需鉴权，appId=" + bimGeoApi.getAppId());
            }
        }
        request.contentType(bimGeoApi.getContentType());
        if (BimGeoRequestDataMethod.FORM.getValue().equals(bimGeoApi.getDataMethod())) {
            request.form(Convert.toMap(String.class, Object.class, requestParam));
        } else {
            request.body(JSONUtil.parse(requestParam).toString());
        }
        return request;
    }

    @Override
    public HttpRequest getRequest(BimGeoApp bimGeoApp, BimGeoApi bimGeoApi, Object requestParam) {
        //获取鉴权配置
        BimGeoAppAuthConfig authConfig = bimGeoAppService.getAuthConfig(bimGeoApp.getId());
        //获取token信息
        String token = bimGeoAppAuthService.auth(bimGeoApp.getId());
        String url = bimGeoApp.getApiUrl() + bimGeoApi.getPath();
        HttpRequest request = new HttpRequest(url)
                .method(BimGeoRequestMethod.methodOf(bimGeoApi.getApiMethod()))
                .header(authConfig.getTokenHeaderKey(), token)
                .contentType(bimGeoApi.getContentType());
        if (BimGeoRequestDataMethod.FORM.getValue().equals(bimGeoApi.getDataMethod())) {
            request.form(Convert.toMap(String.class, Object.class, requestParam));
        } else {
            request.body(JSONUtil.parse(requestParam).toString());
        }
        return request;
    }

    private BimGeoApi queryBimGeoApi(Integer apiId) {
        return new LambdaQueryChainWrapper<>(baseMapper)
                .eq(BimGeoApi::getId, apiId)
                .eq(BimGeoApi::getEnableFlag, YesOrNotEnum.Y.getCode())
                .one();
    }


    @Override
    public BimGeoApi findForBusinessType(Integer appId, String businessType) {
        return new LambdaQueryChainWrapper<>(baseMapper)
                .eq(BimGeoApi::getAppId, appId)
                .eq(businessType != null, BimGeoApi::getBusinessType, businessType)
                .eq(BimGeoApi::getEnableFlag, YesOrNotEnum.Y.getCode())
                .one();
    }

    @Override
    public List<BimGeoApi> geoApiByApp(Integer appId, Integer apiId) {
        List<BimGeoApi> bimGeoApiList = new LambdaQueryChainWrapper<>(baseMapper)
                .eq(appId != null, BimGeoApi::getAppId, appId)
                .eq(apiId != null, BimGeoApi::getId, apiId)
                .eq(BimGeoApi::getEnableFlag, YesOrNotEnum.Y.getCode())
                .list();
        if(CollUtil.isNotEmpty(bimGeoApiList)){
            for(BimGeoApi bimGeoApi : bimGeoApiList){
                BimGeoApp bimGeoApp =  bimGeoAppService.getById(bimGeoApi.getAppId());
                bimGeoApi.setAppName(bimGeoApp.getAppName());
            }
        }
        return bimGeoApiList;
    }


}
